/*
 * @Author: byron
 * @Date: 2021-09-25 22:11:00
 * @LastEditTime: 2022-02-19 21:52:45
 */
import axios from 'axios'

import
messageInfo
from '@/components/message/index.js'

import
loadingInfo
from '@/components/loading/index.js'

const BASE_AXIOS_URL = process.env.VUE_APP_URL ?
    process.env.VUE_APP_URL :
    'http://127.0.0.1:9990/api'



// 通用的axios实例
let loading = null
let loadingCount = 0



export const request = function (axiosOptions, customOptions) {
    const instance = axios.create({
        baseURL: BASE_AXIOS_URL,
        timeout: 1000000,
    })

    // 自定义配置
    let custom_options = Object.assign({
        repeat_request_cancel: true, // 是否开启取消重复请求, 默认为 true
        loading: false, // 是否开启loading效果
    }, customOptions);
    let loadingInstance = null
    instance.interceptors.request.use(
        config => {
            removePending(config);
            custom_options.repeat_request_cancel && addPending(config);
            if (custom_options.loading) {
                if (!loading) {
                    loadingInstance = loadingInfo.CreateLoading()
                    // store.commit(SET_AXIOS_LOADING, true)
                }
                loadingCount++
            }

            return config;
        },
        error => {
            return Promise.reject(error);
        }
    );

    instance.interceptors.response.use(function (response) {
        if (custom_options.loading) {
            loadingCount--
            // 当前页面全部请求完毕之后关闭loading的加载
            if (loadingCount === 0) {
                loadingInstance.close()
                loading = null
                // store.commit(SET_AXIOS_LOADING, false)
            }
        }

        removePending(response.config);
        return response.data
        // 2xx 范围内的状态码都会触发该函数。
        // 对响应数据做点什么
    }, handleError)
    return instance(axiosOptions)
}


// 请求错误函数
function handleError(error) {
    error.config && removePending(error.config);
    httpErrorStatusHandle(error)
    throw error
}




const pendingMap = new Map();

/**
 * 生成每个请求唯一的键
 * @param {*} config 
 * @returns string
 */
function getPendingKey(config) {
    let {
        url,
        method,
        params,
        data
    } = config;
    if (typeof data === 'string') data = JSON.parse(data); // response里面返回的config.data是个字符串对象
    return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&');
}

/**
 * 储存每个请求唯一值, 也就是cancel()方法, 用于取消请求
 * @param {*} config 
 */
function addPending(config) {
    const pendingKey = getPendingKey(config);
    config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
        if (!pendingMap.has(pendingKey)) {
            pendingMap.set(pendingKey, cancel);
        }
    });
}


// axios.js
/**
 * 删除重复的请求
 * @param {*} config 
 */
function removePending(config) {
    const pendingKey = getPendingKey(config);
    if (pendingMap.has(pendingKey)) {
        const cancelToken = pendingMap.get(pendingKey);
        cancelToken(pendingKey);
        pendingMap.delete(pendingKey);
    }
}

/**
 * 处理异常
 * @param {*} error 
 */
function httpErrorStatusHandle(error) {
    console.log('xxxxxx', error)
    // 处理被取消的请求
    if (axios.isCancel(error)) return console.error('请求的重复请求：' + error.message);
    let message = '';
    if (error && error.response) {
        switch (error.response.status) {
            case 302:
                message = '接口暂时重定向';
                break;
            case 400:
                message = '请求报文参数不正确';
                break;
            case 401:
                message = '未登录或者登录已超时';
                break;
            case 403:
                message = '您无权操作';
                break;
            case 404:
                message = `请求地址出错: ${error.response.config.url}`;
                break; // 在正确域名下
            case 408:
                message = '请求超时';
                break;
            case 409:
                message = '系统已存在相同数据';
                break;
            case 500:
                message = '服务器内部错误';
                break;
            case 501:
                message = '服务未实现';
                break;
            case 502:
                message = '网关错误';
                break;
            case 503:
                message = '服务不可用';
                break;
            case 504:
                message = '服务暂时无法访问，请稍后再试';
                break;
            case 505:
                message = 'HTTP版本不受支持';
                break;
            default:
                message = '异常问题，请联系管理员！';
                break
        }
    }
    if (error.message.includes('timeout')) message = '网络请求超时！';
    if (error.message.includes('Network')) message = window.navigator.onLine ? '服务端异常！' : '您断网了！';

    messageInfo.CreateMessage(message)

}